import os
from datetime import datetime
from collections import Counter, defaultdict
import matplotlib.pyplot as plt
import re
from itertools import pairwise
import numpy as np
from matplotlib.dates import DateFormatter
import pandas as pd


class ReportGenerator:
    def __init__(self):
        self.report_dir = os.path.join(
            os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "reports"
        )
        if not os.path.exists(self.report_dir):
            os.makedirs(self.report_dir)

        # 设置中文字体
        plt.rcParams["font.sans-serif"] = ["SimHei"]  # 用来正常显示中文标签
        plt.rcParams["axes.unicode_minus"] = False  # 用来正常显示负号

    def clean_pose_name(self, pose_str):
        """清理姿态名称，去除评分等额外信息"""
        return re.sub(r"\s*\(.*\)", "", pose_str)

    def analyze_pose_transitions(self, filtered_poses):
        """分析姿态转换模式"""
        transitions = []
        for prev, curr in pairwise(filtered_poses):
            if prev != curr:
                transitions.append(f"{prev} → {curr}")
        transition_counts = Counter(transitions)
        return dict(
            sorted(transition_counts.items(), key=lambda x: x[1], reverse=True)[:10]
        )

    def analyze_time_periods(self, pose_history_data):
        """分析不同时间段的姿态分布"""
        df = pd.DataFrame(pose_history_data)
        df["timestamp"] = pd.to_datetime(df["timestamp"])
        df["hour"] = df["timestamp"].dt.hour
        hourly_poses = defaultdict(Counter)

        for hour, group in df.groupby("hour"):
            hourly_poses[hour] = Counter(group["pose"].apply(self.clean_pose_name))
        return dict(sorted(hourly_poses.items()))

    def detect_prolonged_poses(self, filtered_poses, threshold_seconds=300):
        """检测持续时间过长的姿态"""
        current_pose = filtered_poses[0]
        current_count = 1
        prolonged_poses = []

        for pose in filtered_poses[1:]:
            if pose == current_pose:
                current_count += 1
            else:
                duration = current_count * 0.033  # 转换为秒
                if duration > threshold_seconds:
                    prolonged_poses.append({"pose": current_pose, "duration": duration})
                current_pose = pose
                current_count = 1

        return prolonged_poses

    def create_trend_chart(self, pose_history_data, timestamp):
        """创建姿态趋势图"""
        df = pd.DataFrame(pose_history_data)
        df["timestamp"] = pd.to_datetime(df["timestamp"])

        plt.figure(figsize=(15, 6))
        poses = df["pose"].unique()
        for pose in poses:
            mask = df["pose"] == pose
            plt.plot(
                df[mask]["timestamp"],
                df[mask]["confidence"],
                label=pose,
                marker="o",
                markersize=2,
            )

        plt.title("姿态识别置信度趋势")
        plt.xlabel("时间")
        plt.ylabel("置信度")
        plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
        plt.grid(True)

        trend_path = os.path.join(self.report_dir, f"pose_trend_{timestamp}.png")
        plt.savefig(trend_path, dpi=300, bbox_inches="tight")
        plt.close()
        return trend_path

    def generate(self, pose_history_data):
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        report_path = os.path.join(self.report_dir, f"pose_report_{timestamp}.html")

        # 优化姿态数据处理
        poses = [self.clean_pose_name(data["pose"]) for data in pose_history_data]

        # 过滤掉短暂的不稳定状态
        filtered_poses = []
        for i, pose in enumerate(poses):
            if i > 0 and i < len(poses) - 1:
                # 如果当前是不稳定状态，但前后都是同一个稳定姿态，则使用该稳定姿态
                if pose == "姿态不稳定" and poses[i - 1] == poses[i + 1]:
                    filtered_poses.append(poses[i - 1])
                else:
                    filtered_poses.append(pose)
            else:
                filtered_poses.append(pose)

        # 计算姿态统计
        pose_counts = Counter(filtered_poses)
        total_frames = len(filtered_poses)
        pose_durations = {pose: count * 0.033 for pose, count in pose_counts.items()}

        # 按照数量降序排列，便于查看
        sorted_items = sorted(pose_counts.items(), key=lambda x: x[1], reverse=True)
        values = [count for _, count in sorted_items]  # 确保在使用前定义values
        labels = [
            f"{pose}\n{count/total_frames*100:.1f}%" for pose, count in sorted_items
        ]

        # 生成饼图
        plt.figure(figsize=(12, 8))  # 加大图表尺寸
        plt.rcParams["font.sans-serif"] = ["SimHei"]
        plt.rcParams["axes.unicode_minus"] = False

        # 调整饼图大小和布局
        plt.pie(
            values,
            labels=labels,
            autopct="%1.1f%%",
            startangle=90,  # 从90度开始绘制
            counterclock=False,  # 顺时针方向
            textprops={"size": 14},
        )  # 加大文字大小
        plt.title(
            "姿态分布统计\n(总帧数: {})".format(total_frames), pad=20, fontsize=16
        )

        # 调整布局
        plt.tight_layout()

        chart_path = os.path.join(self.report_dir, f"pose_chart_{timestamp}.png")
        plt.savefig(chart_path, dpi=300, bbox_inches="tight")
        plt.close()

        # 生成趋势图
        trend_chart_path = self.create_trend_chart(pose_history_data, timestamp)

        # 分析姿态转换
        pose_transitions = self.analyze_pose_transitions(filtered_poses)

        # 分析时间段分布
        hourly_analysis = self.analyze_time_periods(pose_history_data)

        # 检测异常姿态
        prolonged_poses = self.detect_prolonged_poses(filtered_poses)

        # 生成HTML报告，优化样式
        html_content = f"""
        <html>
        <head>
            <title>姿态分析报告</title>
            <meta charset="utf-8">
            <style>
                body {{ 
                    font-family: Arial, sans-serif; 
                    margin: 0;
                    padding: 20px;
                    background-color: #f5f5f5;
                }}
                .container {{ 
                    max-width: 1200px; 
                    margin: 0 auto;
                    background-color: white;
                    padding: 30px;
                    border-radius: 10px;
                    box-shadow: 0 0 10px rgba(0,0,0,0.1);
                }}
                .chart {{ 
                    margin: 40px 0;
                    text-align: center;
                }}
                .chart img {{
                    max-width: 100%;
                    height: auto;
                }}
                table {{ 
                    width: 100%;
                    border-collapse: collapse;
                    margin: 20px 0 40px 0;
                }}
                th, td {{ 
                    padding: 12px 8px;
                    border: 1px solid #ddd;
                    text-align: center;
                }}
                th {{ 
                    background-color: #f8f9fa;
                    font-weight: bold;
                }}
                h1, h2 {{ 
                    color: #333;
                    margin-top: 30px;
                }}
                p {{ 
                    color: #666;
                    margin-bottom: 20px;
                }}
                tr:nth-child(even) {{
                    background-color: #f8f9fa;
                }}
                .warning {{
                    background-color: #fff3cd;
                    border: 1px solid #ffeeba;
                    color: #856404;
                    padding: 15px;
                    border-radius: 5px;
                    margin: 20px 0;
                }}
            </style>
        </head>
        <body>
            <div class="container">
                <h1>姿态分析报告</h1>
                <p>生成时间：{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
                
                <h2>统计摘要</h2>
                <table>
                    <tr>
                        <th style="width: 25%">姿态类型</th>
                        <th style="width: 25%">出现次数</th>
                        <th style="width: 25%">持续时间(秒)</th>
                        <th style="width: 25%">占比</th>
                    </tr>
                    {"".join(f'<tr><td>{pose}</td><td>{count}</td><td>{pose_durations[pose]:.1f}</td><td>{count/total_frames*100:.1f}%</td></tr>' for pose, count in sorted_items)}
                </table>

                <div class="chart">
                    <h2>姿态分布图</h2>
                    <img src="{os.path.basename(chart_path)}" alt="姿态分布图">
                </div>

                <h2>姿态趋势分析</h2>
                <div class="chart">
                    <img src="{os.path.basename(trend_chart_path)}" alt="姿态趋势图">
                </div>

                <h2>姿态转换分析</h2>
                <table>
                    <tr>
                        <th>转换模式</th>
                        <th>发生次数</th>
                    </tr>
                    {"".join(f'<tr><td>{trans}</td><td>{count}</td></tr>' for trans, count in pose_transitions.items())}
                </table>

                <h2>异常姿态警告</h2>
                <div class="warning">
                    {"<br>".join(f"警告：{p['pose']}姿态持续时间过长 ({p['duration']:.1f}秒)" for p in prolonged_poses)}
                </div>

                <h2>时间段分布</h2>
                <table>
                    <tr>
                        <th>时段</th>
                        <th>主要姿态</th>
                        <th>出现次数</th>
                    </tr>
                    {"".join(f'<tr><td>{hour}时</td><td>{list(poses.keys())[0]}</td><td>{list(poses.values())[0]}</td></tr>' for hour, poses in hourly_analysis.items() if poses)}
                </table>

                <h2>详细记录</h2>
                <div style="overflow-x: auto;">
                    <table>
                        <tr>
                            <th style="width: 33%">时间</th>
                            <th style="width: 34%">姿态</th>
                            <th style="width: 33%">置信度</th>
                        </tr>
                        {"".join(f'<tr><td>{data["timestamp"]}</td><td>{data["pose"]}</td><td>{data["confidence"]:.2f}</td></tr>' for data in pose_history_data)}
                    </table>
                </div>
            </div>
        </body>
        </html>
        """

        with open(report_path, "w", encoding="utf-8") as f:
            f.write(html_content)

        return report_path
